package com.zt.ztlibrary.adapter;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.zt.ztlibrary.adapter.viewinjector.IViewInjector;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 作者:zt
 * 时间:on 18/12/26
 * 说明: RecyclerView 通用适配器
 */
public abstract class ZTAdapter extends AbstractZTAdapter {

    private static final int WHAT_NOTIFY_DATA_SET_CHANGED = 1;//通知更新数据

    /**
     * 头部 布局 和 底部布局
     */
    private final static int TYPE_EX = -100;

    private List<SlimExViewHolder> headerItems;//头部布局
    private List<SlimExViewHolder> footerItems;//底部布局

    public ZTAdapter() {
    }

    protected List<?> data;//数据集合
    private IViewHolderCreator defaultCreator = null;//默认处理数据
    /**
     * 区分几种 类型
     */
    private List<Integer> dataTypes = new ArrayList<>();//不同数据类型不同资源文件下标

    /**
     * 每种类型保存对应的布局
     */
    private Map<Integer, IViewHolderCreator> creators = new HashMap<>();


    /**
     * 运行在 ui线程的 handler , 作用是, 在子线程添加数据, 判断之后在ui显示更新数据
     */
    private Handler uiHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void dispatchMessage(Message msg) {
            switch (msg.what) {
                case WHAT_NOTIFY_DATA_SET_CHANGED://通知更新数据
                    notifyDataSetChanged();
                    break;
            }
            super.dispatchMessage(msg);
        }
    };

    /**
     * 注册一个布局处理
     *
     * @param layoutRes    布局id
     * @param slimInjector 布局处理
     * @param <T>
     * @return
     */
    public <T> ZTAdapter register(final int layoutRes, final ZTInjector<T> slimInjector) {
        //将当前资源文件id 保存起来
        dataTypes.add(layoutRes);
        //将资源文件id 作为map 的key保存对应处理数据的类
        creators.put(layoutRes, new IViewHolderCreator<T>() {
            @Override
            public SlimTypeViewHolder<T> create(ViewGroup parent) {
                return new SlimTypeViewHolder<T>(parent, layoutRes) {
                    @Override
                    protected void onBind(T data, IViewInjector injector) {
                        slimInjector.onInject(data, injector);
                    }
                };
            }
        });
        return this;
    }


    public int getHeaderSize() {
        return headerItems == null ? 0 : headerItems.size();
    }

    public int getFooterSize() {
        return footerItems == null ? 0 : footerItems.size();
    }

    /**
     * 添加一个列表头布局
     *
     * @param view
     * @return
     */
    public ZTAdapter addHeader(View view) {
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams
                .MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        view.setLayoutParams(params);
        if (headerItems == null) {
            headerItems = new ArrayList<>();
        }
        headerItems.add(new SlimExViewHolder(view));
        notifyDataSetChanged();
        return this;
    }

    /**
     * 添加一个列表底部布局
     *
     * @param view
     * @return
     */
    public ZTAdapter addFooter(View view) {
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams
                .MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        view.setLayoutParams(params);
        if (footerItems == null) {
            footerItems = new ArrayList<>();
        }
        footerItems.add(new SlimExViewHolder(view));
        notifyDataSetChanged();
        return this;
    }

    public ZTAdapter addHeader(Context context, int layoutRes) {
        return addHeader(LayoutInflater.from(context).inflate(layoutRes, null));
    }

    public ZTAdapter addFooter(Context context, int layoutRes) {
        return addFooter(LayoutInflater.from(context).inflate(layoutRes, null));
    }


    /**
     * 获取当前 下标对象
     *
     * @param position
     * @return
     */
    @Override
    public Object getItem(int position) {
        //判断下标位置如果没有大于 所添加的头部布局总数, 就返回头部布局
        if (position < getHeaderSize()) {
            return headerItems.get(position);
        } else {
            //如果超过头部下标 并且没有超过添加数据的总数 就正常返回当前下标数据
            position -= getHeaderSize();
            if (position < getItemCount()) {
                return getParentItem(position);
            } else {//如果超过添加数据 则返回底部布局
                position -= getItemCount();
                if (position < getFooterSize()) {
                    return footerItems.get(position);
                } else {
                    return null;
                }
            }
        }
    }

    public Object getParentItem(int position) {
        return data == null || data.size() <= position ? null : data.get(position);
    }


    /**
     * 获取当前条目对应的布局类型
     *
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        //临时保存 下标, 需要做到运算 , 避免把原下标修改
        int tempPosition = position;
        //判断当前下标是否超过 头部总数 , 如果没有就返回头部类型 下标
        if (tempPosition < getHeaderSize()) {
            return TYPE_EX - tempPosition;
        } else {
            //如果超过头部下标 并且没有超过添加数据的总数 就正常返回当前下标 类型
            tempPosition -= getHeaderSize();
            if (tempPosition < getParentItemCount()) {
                return getParentItemViewType(position);
            } else {//如果超过添加数据 则返回底部布局 类型
                tempPosition -= getParentItemCount();
                if (tempPosition < getFooterSize()) {
                    return TYPE_EX - tempPosition - getHeaderSize();
                } else {
                    return TYPE_EX - getHeaderSize() - getFooterSize();
                }
            }
        }
    }

    /**
     * 获取当前条目具体的 type , 区分几种布局
     *
     * @param position
     * @return
     */
    public int getParentItemViewType(int position) {
        int resType = 0;
        try {
            //获取当下标对应的数据
            Object item = getItem(position);
            //抛出一个接口处理 该数据 对应的资源类型
            resType = getItemViewType(item, position);
        } catch (Exception e) {
            throw new IllegalArgumentException("判断数据对应的资源文件出错");
        }
        return dataTypes.indexOf(resType);
    }


    /**
     * 获取当前处理布局 类
     *
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public ZTViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ZTViewHolder viewHolder;
        if (viewType <= TYPE_EX) {
            Object item = getExItem(TYPE_EX - viewType);
            viewHolder = (ZTViewHolder) item;
        } else {
            //获取当前类型,下标保存的 布局资源文件id
            Integer dataType = dataTypes.get(viewType);
            //根据资源id 文件获取 对应的数据处理类
            IViewHolderCreator creator = creators.get(dataType);
            if (creator == null) {
                if (defaultCreator == null) {
                    throw new IllegalArgumentException(String.format("Neither the TYPE: %s not The " +
                            "DEFAULT injector found...", viewType));
                }
                creator = defaultCreator;
            }
            //其他情况 调用 父类处理
            viewHolder = creator.create(parent);
        }
        return viewHolder;
    }


    /**
     * 更新数据
     *
     * @param data 数据集合
     * @return
     */
    public ZTAdapter updateData(List<?> data) {
        if (getItemCount() == 0 || this.data == null || this.data.size() == 0) {
            this.data = data;
            //在主线程
            if (Looper.myLooper() == Looper.getMainLooper()) {
                notifyDataSetChanged();
            } else {
                //否则发送通知 在ui线程更新数据
                uiHandler.removeMessages(WHAT_NOTIFY_DATA_SET_CHANGED);
                uiHandler.sendEmptyMessage(WHAT_NOTIFY_DATA_SET_CHANGED);
            }
        }
        return this;
    }

    public List<?> getData() {
        return data;
    }

    private Object getExItem(int position) {
        //判断当前下标是头部
        if (position < getHeaderSize()) {
            return headerItems.get(position);
        } else {
            position -= getHeaderSize();
            if (position < getFooterSize()) {
                return footerItems.get(position);
//            } else {
//                return moreLoader;
            }
        }
        return null;
    }

    @Override
    public int getItemCount() {
        return getFooterSize() + getHeaderSize() + (data == null ? 0 : data.size());
    }

    public int getParentItemCount() {
        return data == null ? 0 : data.size();
    }

    /**
     * 给控件设置 adapter
     *
     * @param recyclerView
     * @return
     */
    public ZTAdapter attachTo(RecyclerView recyclerView) {
        recyclerView.setAdapter(this);
        return this;
    }

    protected interface IViewHolderCreator<T> {
        SlimTypeViewHolder<T> create(ViewGroup parent);
    }

    /**
     * 根据数据类型 返回资源id
     *
     * @param model    数据
     * @param position 当前下标
     * @return 布局资源文件
     */
    public abstract int getItemViewType(Object model, int position);

    static abstract class SlimTypeViewHolder<T> extends ZTViewHolder<T> {

        SlimTypeViewHolder(ViewGroup parent, int itemLayoutRes) {
            super(parent, itemLayoutRes);
        }
    }

    private class SlimExViewHolder extends ZTViewHolder<Object> {


        public SlimExViewHolder(View itemView) {
            super(itemView);
        }

        @Override
        protected void onBind(Object data, IViewInjector injector) {

        }
    }


}
